package com.jzy.service.impl;

import com.jzy.constant.WebConstant;
import com.jzy.dto.Types;
import com.jzy.entity.Vo.ContentVo;
import com.jzy.exception.TipException;
import com.jzy.repository.ContentRepository;
import com.jzy.service.IContentService;
import com.jzy.service.IMetaService;
import com.jzy.service.IRelationshipService;
import com.jzy.util.DateKit;
import com.jzy.util.PredicateUtil;
import com.jzy.util.TaleUtils;
import com.jzy.util.Tools;
import com.vdurmont.emoji.EmojiParser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;

@Service
public class ContentServiceImpl implements IContentService {

    @Resource
    private ContentRepository contentRepository;

    @Resource
    private IMetaService metasService;

    @Resource
    private IRelationshipService relationshipService;

    @Override
    public ContentVo getContents(String id) {
        if (StringUtils.isNotBlank(id)) {
            if (Tools.isNumber(id)) {
                ContentVo contentVo = contentRepository.findById(Integer.parseInt(id)).orElse(null);
                if (contentVo != null) {
                    contentVo.setHits(contentVo.getHits() + 1);
                    contentRepository.saveAndFlush(contentVo);
                }
                return contentVo;
            } else {
                List<ContentVo> allBySlug = contentRepository.findAllBySlug(id);
                if (allBySlug.size() != 1) {
                    throw new TipException("query content by id and return is not one");
                }
                return allBySlug.get(0);
            }
        }
        return null;
    }

    @Override
    public Page<ContentVo> getContents(Integer p, Integer limit) {
        Sort by = PredicateUtil.getOrders();
        Specification<ContentVo> specification = PredicateUtil.getContentVoSpecification();
        PageRequest of = PageRequest.of(p - 1, limit, by);
        return contentRepository.findAll(specification, of);
    }

    @Override
    public void publish(ContentVo contents) {
        if (null == contents) {
            throw new TipException("文章对象为空");
        }
        if (StringUtils.isBlank(contents.getTitle())) {
            throw new TipException("文章标题不能为空");
        }
        if (StringUtils.isBlank(contents.getContent())) {
            throw new TipException("文章内容不能为空");
        }
        int titleLength = contents.getTitle().length();
        if (titleLength > WebConstant.MAX_TITLE_COUNT) {
            throw new TipException("文章标题过长");
        }
        int contentLength = contents.getContent().length();
        if (contentLength > WebConstant.MAX_TEXT_COUNT) {
            throw new TipException("文章内容过长");
        }
        if (null == contents.getAuthorId()) {
            throw new TipException("请登录后发布文章");
        }
        if (StringUtils.isNotBlank(contents.getSlug())) {
            if (contents.getSlug().length() < 5) {
                throw new TipException("路径太短了");
            }
            if (!TaleUtils.isPath(contents.getSlug())) throw new TipException("您输入的路径不合法");
            Specification<ContentVo> specification = (Specification<ContentVo>) (root, query, criteriaBuilder) -> {
                ArrayList<Predicate> predicates = new ArrayList<>();
                predicates.add(criteriaBuilder.equal(root.get("slug"),contents.getSlug()));
                predicates.add(criteriaBuilder.equal(root.get("type"),contents.getType()));
                int size = predicates.size();
                return criteriaBuilder.and(predicates.toArray(new Predicate[size]));
            };
            long count = contentRepository.count(specification);
            if (count > 0) throw new TipException("该路径已经存在，请重新输入");
        } else {
            contents.setSlug(null);
        }
        contents.setContent(EmojiParser.parseToAliases(contents.getContent()));
        int time = DateKit.getCurrentUnixTime();
        contents.setCreated(time);
        contents.setModified(time);
        contents.setHits(0);
        contents.setCommentsNum(0);
        contentRepository.saveAndFlush(contents);
        //标签
        String tags = contents.getTags();
        //分类
        String categories = contents.getCategories();
        Integer cid = contents.getCid();
        metasService.saveMetas(cid, tags, Types.TAG.getType());
        metasService.saveMetas(cid, categories, Types.CATEGORY.getType());
    }

    @Override
    public Page<ContentVo> getArticlesWithPage(int page, int limit, String type) {
        Sort by = PredicateUtil.getOrders();
        Specification<ContentVo> specification = (Specification<ContentVo>) (root, query, criteriaBuilder) -> PredicateUtil.getPredicateByType(type, root, criteriaBuilder);
        PageRequest of = PageRequest.of(page - 1, limit, by);
        return contentRepository.findAll(specification, of);
    }

    @Override
    public void updateArticle(ContentVo contents) {
        if (null == contents || null == contents.getCid()) {
            throw new TipException("文章对象不能为空");
        }
        if (StringUtils.isBlank(contents.getTitle())) {
            throw new TipException("文章标题不能为空");
        }
        if (StringUtils.isBlank(contents.getContent())) {
            throw new TipException("文章内容不能为空");
        }
        if (contents.getTitle().length() > 200) {
            throw new TipException("文章标题过长");
        }
        if (contents.getContent().length() > 65000) {
            throw new TipException("文章内容过长");
        }
        if (null == contents.getAuthorId()) {
            throw new TipException("请登录后发布文章");
        }
        if (StringUtils.isBlank(contents.getSlug())) {
            contents.setSlug(null);
        }
        int time = DateKit.getCurrentUnixTime();
        contents.setModified(time);
        contents.setContent(EmojiParser.parseToAliases(contents.getContent()));
        //修改文章信息
        contentRepository.saveNotNull(contents);
        Integer cid = contents.getCid();
        //修改中间表信息
        relationshipService.deleteById(cid, null);
        metasService.saveMetas(cid, contents.getTags(), Types.TAG.getType());
        metasService.saveMetas(cid, contents.getCategories(), Types.CATEGORY.getType());
    }

    @Override
    public void updateContentByCid(ContentVo contentVo) {
        if (null != contentVo && null != contentVo.getCid()) {
            contentRepository.saveNotNull(contentVo);
        }
    }
}
